package vip.xiaomaoxiaoke.mybatisplusmax;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;



import java.util.*;

public class LambdaMyBatisPlusMax<T> implements MyBatisPlusMax<T> {


    private LambdaQueryWrapper<T> wrapper;

    private IService<T> iService;


    private LambdaMyBatisPlusMax(IService<T> iService) {
        this.iService = iService;
        this.wrapper = new LambdaQueryWrapper<T>();
    }


    public static <T> LambdaMyBatisPlusMax<T> of(IService<T> iService){

        return new LambdaMyBatisPlusMax<T>(iService);
    }

    public List<T> list() {
        return iService.list(wrapper);
    }

    public long count() {
        return iService.count(wrapper);
    }

    public T one() {
        return iService.getOne(wrapper);
    }


    public Page<T> page(Integer pageNo, Integer size) {
        pageNo= Optional.ofNullable(pageNo).orElse(1);
        size = Optional.ofNullable(size).orElse(10);
        return iService.page(new Page<>(pageNo,size),wrapper);
    }

    private LambdaMyBatisPlusMax(LambdaQueryWrapper<T> wrapper) {
        this.wrapper = wrapper;
    }

    /**
     * 等值查询
     * */
    @Override
    public MyBatisPlusMax<T> eq(Boolean flag, SFunction<T, ?> function, Object val) {
        flag = Optional.ofNullable(flag).orElseGet(()-> !checkObject(val));
        wrapper.eq(flag,function,val);
        return this;
    }

    @Override
    public MyBatisPlusMax<T> between(Boolean flag, SFunction<T, ?> function, Object val1, Object val2) {
        flag = Optional.ofNullable(flag).orElseGet(()-> !checkObject(val1) && !checkObject(val2));
        wrapper.between(flag,function,val1,val2);
        return this;
    }

    @Override
    public MyBatisPlusMax<T> notBetween(Boolean flag, SFunction<T, ?> function, Object val1, Object val2) {
        flag = Optional.ofNullable(flag).orElseGet(()-> !checkObject(val1) && !checkObject(val2));
        wrapper.notBetween(flag,function,val1,val2);
        return this;
    }

    @Override
    public MyBatisPlusMax<T> notIn(Boolean flag, SFunction<T, ?> function, Collection<?> values) {

        flag = Optional.ofNullable(flag).orElseGet(()-> !checkObject(values));
        wrapper.notIn(flag,function,values);
        return this;
    }

    @Override
    public MyBatisPlusMax<T> in(Boolean flag, SFunction<T, ?> function, Collection<?> values) {

        flag = Optional.ofNullable(flag).orElseGet(()-> !checkObject(values));
        wrapper.in(flag,function,values);
        return this;
    }

    @Override
    public MyBatisPlusMax<T> last(Boolean condition, String lastSqls) {
        condition = Optional.ofNullable(condition).orElseGet(()-> !checkObject(lastSqls));
        wrapper.last(condition,lastSqls);
        return this;
    }

    @Override
    public MyBatisPlusMax<T> isNotNull(Boolean condition, SFunction<T, ?> function) {
        wrapper.isNotNull(condition,function);
        return this;
    }

    @Override
    public MyBatisPlusMax<T> isNull(Boolean condition, SFunction<T, ?> function) {
        wrapper.isNull(condition,function);
        return this;
    }

    @Override
    public MyBatisPlusMax<T> like(Boolean condition, SFunction<T, ?> function, Object val) {
        condition = Optional.ofNullable(condition).orElseGet(()-> !checkObject(val));
        wrapper.like(condition,function,val);
        return this;
    }

    @Override
    public MyBatisPlusMax<T> likeLeft(Boolean condition, SFunction<T, ?> function, Object val) {
        condition = Optional.ofNullable(condition).orElseGet(()-> !checkObject(val));
        wrapper.likeLeft(condition,function,val);
        return this;
    }

    @Override
    public MyBatisPlusMax<T> likeRight(Boolean condition, SFunction<T, ?> function, Object val) {
        condition = Optional.ofNullable(condition).orElseGet(()-> !checkObject(val));
        wrapper.likeRight(condition,function,val);
        return this;
    }

    @Override
    public MyBatisPlusMax<T> ne(Boolean flag, SFunction<T, ?> function, Object val) {
        flag = Optional.ofNullable(flag).orElseGet(()-> !checkObject(val));
        wrapper.ne(flag,function,val);
        return this;
    }

    @Override
    public MyBatisPlusMax<T> gt(Boolean flag, SFunction<T, ?> function, Object val) {
        flag = Optional.ofNullable(flag).orElseGet(()-> !checkObject(val));
        wrapper.gt(flag,function,val);
        return this;
    }

    @Override
    public MyBatisPlusMax<T> groupBy(Boolean flag, SFunction<T, ?> function) {
        wrapper.groupBy(flag,function);
        return this;
    }

    @Override
    public MyBatisPlusMax<T> orderByAsc(Boolean flag, SFunction<T, ?> function) {
        wrapper.orderByAsc(flag,function);
        return this;
    }

    @Override
    public MyBatisPlusMax<T> orderByDesc(Boolean flag, SFunction<T, ?> function) {
        wrapper.orderByDesc(flag,function);
        return this;
    }


    @Override
    public MyBatisPlusMax<T> ge(Boolean flag, SFunction<T, ?> function, Object val) {
        flag = Optional.ofNullable(flag).orElseGet(()-> !checkObject(val));
        wrapper.ge(flag,function,val);
        return this;
    }

    @Override
    public MyBatisPlusMax<T> lt(Boolean flag, SFunction<T, ?> function, Object val) {
        flag = Optional.ofNullable(flag).orElseGet(()-> !checkObject(val));
        wrapper.lt(flag,function,val);
        return this;
    }

    @Override
    public MyBatisPlusMax<T> notLike(Boolean condition, SFunction<T, ?> function, Object val) {
        condition = Optional.ofNullable(condition).orElseGet(()-> !checkObject(val));
        wrapper.notLike(condition,function,val);
        return this;
    }

    @Override
    public MyBatisPlusMax<T> le(Boolean flag, SFunction<T, ?> function, Object val) {
        flag = Optional.ofNullable(flag).orElseGet(()-> !checkObject(val));
        wrapper.le(flag,function,val);
        return this;
    }

    @Override
    public MyBatisPlusMax<T> or(Boolean condition) {
        wrapper.or(condition);
        return this;
    }










    /**
     * 数据为空则返回true
     * */
    private boolean checkObject(Object val) {
        if (Objects.isNull(val)) return true;
        // TODO
        if (val instanceof String) {
            String str = (String) val;
            if (str.trim().length() == 0) {
                return true;
            }
        }
        if (val instanceof Collection) {
            Collection collection = (Collection) val;
            if (collection.size() == 0) {
                return true;
            }
        }
        return false;
    }



}
